package com.pengliu.controller;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.pengliu.common.bean.OssFile;
import com.pengliu.common.bean.OssFileExample;
import com.pengliu.common.bean.OssFileExample.Criteria;
import com.pengliu.common.bean.OssUser;
import com.pengliu.common.bean.OssUserExample;
import com.pengliu.common.exception.ServiceException;
import com.pengliu.config.BaseController;
import com.pengliu.service.OssFileService;
import com.pengliu.service.OssUserService;
import com.pengliu.util.AESUtil;
import com.pengliu.util.AjaxResult;
import com.pengliu.util.CacheMap;
import com.pengliu.util.Maps;

@Controller
@RequestMapping("/oss")
public class OssManageController extends BaseController{
	
	@Value("${host}")
	private String host;
	
	private static String password = "TM0yEM20G7pSPavF";
	
	@Autowired
	private OssUserService ossUserService;
	
	@Autowired
	private OssFileService ossFileService;
	
	@ResponseBody
	@CrossOrigin
    @RequestMapping(value = "/", method = RequestMethod.POST)
    public AjaxResult upload(
    		String name,							//文件真实名称
        	String key,							//空间目录下的相对路径
        	String policy,						//策略验证认证值
        	String OSSAccessKeyId,		//秘钥值
        	String signature,				//签名值
        	@RequestParam("file") MultipartFile multipartFile
    ) throws Exception {
    	if(StringUtils.isBlank(OSSAccessKeyId)) {
    		throw new ServiceException("参数:OSSAccessKeyId,不能为空");
    	}
    	if(StringUtils.isBlank(signature)) {
    		throw new ServiceException("参数:signature,不能为空");
    	}
    	if(StringUtils.isBlank(policy)) {
    		throw new ServiceException("参数:policy,不能为空");
    	}
    	if(StringUtils.isNotBlank(key) && key.contains("${filename}")) {
    		key = key.replaceAll("\\$\\{filename\\}", "/");
    	}
    	if(StringUtils.isNotBlank(key) && key.contains(".")) {
    		key = key.substring(0,key.lastIndexOf(".")).concat("/");
    	}
    	
    	OssUser ossUser = null;
    	
    	try {
    		//为了能先拿到钥匙
        	Map signatureMap  = JSON.parseObject(AESUtil.decrypt(signature, password),Map.class);
        	
        	String cacheMapKey = OSSAccessKeyId+"_"+signature;
        	Object cacheMap = CacheMap.getValue(cacheMapKey);
        	if(null == cacheMap) {
        		throw new ServiceException("非合法参数值,或参数已过期!请重试...");
        	}
        	String ossUserJson = cacheMap.toString();
        	
        	ossUser = JSON.parseObject(AESUtil.randomStringDecrypt(ossUserJson, signatureMap.get("accessKey").toString()), OssUser.class);
        	
        	if(null == ossUser) {
        		throw new ServiceException("非合法参数值,或参数已过期!请重试...");
        	}
		} catch (Exception e) {
			throw new ServiceException("非合法参数值,或参数已过期!请重试...");
		}
    	
    	
    	OssFile ossFile = null;
    	
		if (!multipartFile.isEmpty()) {
            try {
            	String suffix = name.substring(name.lastIndexOf("."));
            	
            	ossFile = new OssFile();
            	ossFile.setUuid(UUID.randomUUID().toString().replaceAll("-", ""));
            	ossFile.setSysUserId(ossUser.getSysUserId());
            	ossFile.setBucket(ossUser.getBucket());
            	ossFile.setDirPath(key);
            	ossFile.setFileSuffix(suffix);
            	ossFile.setContentType(multipartFile.getContentType());
            	ossFile.setFileSize(multipartFile.getSize());
            	ossFile.setFilePath(ossUser.getBucket()+key+ossFile.getUuid()+suffix);
            	ossFile.setFileTag(name);
            	ossFile.setEnableState(1);
            	ossFile.setCreateTime(System.currentTimeMillis());
            	ossFileService.insert(ossFile);
            	
            	File file = new File(ossFile.getFilePath());
                FileUtils.writeByteArrayToFile(file, multipartFile.getBytes());
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                return AjaxResult.getFailResult("上传失败," + e.getMessage());
            } catch (IOException e) {
                e.printStackTrace();
                return AjaxResult.getFailResult("上传失败," + e.getMessage());
            }
            return AjaxResult.getSuccessrResult(host+"/ossGet"+ossFile.getFilePath());
        } else {
            return AjaxResult.getFailResult("上传失败，因为文件是空的.");
        }
	}
	
    @ResponseBody
    @RequestMapping(value = "/authOss", method = RequestMethod.GET)
	public Map<String,Object> authOss(
		String accessId,
		String accessKey,
		@RequestParam(name="bucket",defaultValue="/bucket_test") String bucket,
		@RequestParam(name="dir",defaultValue="/test") String dir
	) throws Exception{
    	
    	OssUser ossUser = null;
    	
    	if(StringUtils.isBlank(bucket)) {
    		throw new ServiceException("参数:bucket,存储空间目录不能为空");
    	}
    	if(StringUtils.isBlank(dir)) {
    		throw new ServiceException("参数:dir,空间下文件相对路径不能为空");
    	}
    	
		OssUserExample ossUserExample = new OssUserExample();
		ossUserExample.getCriteria()
			.andAccessIdEqualTo(accessId)
			.andAccessKeyEqualTo(accessKey)
			.andBucketEqualTo(bucket)
			.andEnableStateEqualTo(1);
		ossUser = ossUserService.selectOneByExample(ossUserExample);
    	
    	if(null == ossUser) {
    		throw new ServiceException("未找到目录空间,或空间已被停用,请开启或创建目录空间");
    	}
    	
    	accessId = ossUser.getAccessId();
    	//认证失效时间
    	int expireTime = 86400;   //设置认证一天失效
    	ossUser.setExpireTime(System.currentTimeMillis()+(expireTime*1000));
    	
    	String policy = "";
    	
    	try {
			policy = AESUtil.randomStringEncrypt(JSON.toJSONString(ossUser),ossUser.getAccessKey());
		} catch (Exception e) {
			e.printStackTrace();
			throw new ServiceException("加密异常错误");
		}
    	
    	Map<String,Object> signatureMap = Maps.newConcurrentHashMap();
    	signatureMap.put("expireTime", ossUser.getExpireTime());
    	signatureMap.put("accessKey", ossUser.getAccessKey());
    	String signature = AESUtil.encrypt(JSON.toJSONString(signatureMap), password);
    	CacheMap.putKV(accessId+"_"+signature,policy,ossUser.getExpireTime());
    	
    	Map<String,Object> resultMap = new HashMap<String,Object>();
    	resultMap.put("accessid", accessId);
    	resultMap.put("dir", dir);
    	resultMap.put("expire", (ossUser.getExpireTime()/1000));
    	resultMap.put("policy", policy);
    	resultMap.put("signature", signature);
    	resultMap.put("host", host+"/oss/");
    	
		return resultMap;
	}
	
    @RequestMapping("/user-list")
	public ModelAndView userList() {
    	//获取当前登陆用户
    	Integer currentSysUserId = getCurrentSysUser().getId();
    	
    	OssUserExample ossUserExample = new OssUserExample();
    	ossUserExample.getCriteria()
    		.andSysUserIdEqualTo(currentSysUserId);
    	List<OssUser> listOssUsers = ossUserService.selectByExample(ossUserExample);
    	
		ModelAndView modelAndView = this.getModelAndView("/oss/user-list");
		modelAndView.addObject("listMap", listOssUsers);
		return modelAndView;
	}
    
    @RequestMapping("/user-add")
    public ModelAndView userAdd() {
    	ModelAndView modelAndView = this.getModelAndView("/oss/user-add");
    	return modelAndView;
    }
    
    @ResponseBody
    @RequestMapping("/user_add")
    public AjaxResult userAdd(
    	String bucket,
    	Integer enable_state
    ) throws ServiceException {
    	if(StringUtils.isBlank(bucket)) {
    		throw new ServiceException("存放空间目录不能为空");
    	}
    	if(null == enable_state) {
    		throw new ServiceException("启用状态不能为空");
    	}
    	
    	//处理空间名，命名规范(不允许多级目录空间名)
    	bucket = bucket.replaceAll("/", "");
    	bucket = "/".concat(bucket);
    	
    	//获取当前登陆用户
    	Integer currentSysUserId = getCurrentSysUser().getId();
    	
    	String accessId = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 16);
    	String accessKey = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
    	
    	OssUser ossUser = new OssUser();
    	ossUser.setSysUserId(currentSysUserId);
    	ossUser.setAccessId(accessId);
    	ossUser.setAccessKey(accessKey);
    	ossUser.setBucket(bucket);
    	ossUser.setEnableState(enable_state);
    	ossUser.setCreateTime(System.currentTimeMillis());
    	ossUserService.insert(ossUser);
    	
    	//创建存储空间目录
    	new File(bucket).mkdirs();
    	
    	return AjaxResult.getSuccessrResult(true);
    }
    
    @ResponseBody
    @RequestMapping("/user_del")
    public AjaxResult userDel(Integer id) throws ServiceException, Exception {
    	OssUser ossUser = ossUserService.selectByPrimaryKey(id);
    	String bucket = ossUser.getBucket();
    	ossUserService.deleteByPrimaryKey(id);
    	FileUtils.deleteQuietly(new File(bucket));
    	return AjaxResult.getSuccessrResult(true);
    }
    @ResponseBody
    @RequestMapping("/user_stop")
    public AjaxResult userStop(Integer id) throws ServiceException {
    	OssUser ossUser = ossUserService.selectByPrimaryKey(id);
    	String bucket = ossUser.getBucket();
    	ossUser.setEnableState(0);
    	ossUserService.updateByPrimaryKeySelective(ossUser);
    	
    	OssFileExample ossFileExample = new OssFileExample();
    	ossFileExample.getCriteria()
    		.andBucketEqualTo(bucket);
    	OssFile ossFile = new OssFile();
    	ossFile.setEnableState(0);
    	ossFileService.updateByExampleSelective(ossFile, ossFileExample);
    	
    	return AjaxResult.getSuccessrResult(true);
    }
    @ResponseBody
    @RequestMapping("/user_start")
    public AjaxResult userStart(Integer id) throws ServiceException {
    	
    	OssUser ossUser = ossUserService.selectByPrimaryKey(id);
    	String bucket = ossUser.getBucket();
    	ossUser.setEnableState(1);
    	ossUserService.updateByPrimaryKeySelective(ossUser);
    	
    	OssFileExample ossFileExample = new OssFileExample();
    	ossFileExample.getCriteria()
    		.andBucketEqualTo(bucket);
    	OssFile ossFile = new OssFile();
    	ossFile.setEnableState(1);
    	ossFileService.updateByExampleSelective(ossFile, ossFileExample);
    	
    	return AjaxResult.getSuccessrResult(true);
    }
    
    
    @RequestMapping("/file-manage")
	public ModelAndView fileManage(
		String uuid,
		String bucket,
		String fileType,
		String startTimeStr,
		String endTimeStr,
		String fileTag,
		Integer pageNum,
		Integer pageSize
	) throws ServiceException {
    	
    	if(null == pageNum) pageNum = 1;
    	if(null == pageSize) pageSize = 5;
    	
    	Map<String,Object> params = new HashMap<String,Object>();
    	params.put("uuid", uuid);
    	params.put("bucket", bucket);
    	params.put("fileType", fileType);
    	params.put("startTimeStr", startTimeStr);
    	params.put("endTimeStr", endTimeStr);
    	params.put("fileTag", fileTag);
    	params.put("pageNum", pageNum);
    	params.put("pageSize", pageSize);
    	
    	Long startTime = null;
    	Long endTime = null;
    	SimpleDateFormat sdf = null;
    	if(StringUtils.isNotBlank(startTimeStr)) {
    		sdf = new SimpleDateFormat("yyyy-MM-dd");
    		try {
    			startTime = sdf.parse(startTimeStr).getTime();
			} catch (ParseException e) {
				throw new ServiceException("时间格式不正确,需要yyyy-MM-dd");
			}
    	}
    	if(StringUtils.isNotBlank(endTimeStr)) {
    		sdf = new SimpleDateFormat("yyyy-MM-dd");
    		try {
    			endTime = sdf.parse(endTimeStr).getTime();
			} catch (ParseException e) {
				throw new ServiceException("时间格式不正确,需要yyyy-MM-dd");
			}
    	}
    	
    	//获取当前登陆用户
    	Integer currentSysUserId = getCurrentSysUser().getId();
    	
    	OssUserExample ossUserExample = new OssUserExample();
    	ossUserExample.getCriteria().andSysUserIdEqualTo(currentSysUserId);
    	List<OssUser> listOssUser = ossUserService.selectByExample(ossUserExample);
    	
    	PageHelper pageHelper = new PageHelper();
    	pageHelper.startPage(pageNum, pageSize);
    	
    	OssFileExample ossFileExample = new OssFileExample();
    	Criteria criteria = ossFileExample.getCriteria().andSysUserIdEqualTo(currentSysUserId);
    	if(StringUtils.isNotBlank(uuid)) {
    		criteria.andUuidEqualTo(uuid);
    	}
    	if(StringUtils.isNotBlank(bucket)) {
    		criteria.andBucketEqualTo(bucket);
    	}
    	if(StringUtils.isNotBlank(fileType)) {
    		if(fileType.equals("图片")) {
    			criteria.andContentTypeLike("%image%");
    		}else {
    			criteria.andContentTypeNotLike("%image%");
    		}
    	}
    	if(null != startTime) {
    		criteria.andCreateTimeGreaterThanOrEqualTo(startTime);
    	}
    	if(null != endTime) {
    		criteria.andCreateTimeLessThanOrEqualTo(endTime);
    	}
    	if(StringUtils.isNotBlank(fileTag)) {
    		criteria.andFileTagLike("%"+fileTag+"%");
    	}
    	ossFileExample.setOrderByClause(" create_time desc ");
    	List<OssFile> listOssFile = ossFileService.selectByExample(ossFileExample);
    	
    	PageInfo<OssFile> pageInfo = new PageInfo<OssFile>(listOssFile);
    	
		ModelAndView modelAndView = this.getModelAndView("/oss/file-manage");
		modelAndView.addObject("pageInfo", pageInfo);
		modelAndView.addObject("listOssUser", listOssUser);
		modelAndView.addObject("host", host);
		modelAndView.addObject("params",params);
		
		return modelAndView;
	}
    
    @RequestMapping("/file-add")
    public ModelAndView fileAdd() {
    	//获取当前登陆用户
    	Integer currentSysUserId = getCurrentSysUser().getId();
    	
    	OssUserExample ossUserExample = new OssUserExample();
    	ossUserExample.getCriteria().andSysUserIdEqualTo(currentSysUserId);
    	List<OssUser> listOssUser = ossUserService.selectByExample(ossUserExample);
    	
    	ModelAndView modelAndView = this.getModelAndView("/oss/file-add");
    	modelAndView.addObject("listOssUser", listOssUser);
    	return modelAndView;
    }
    
    @ResponseBody
    @RequestMapping("/file_del")
    public AjaxResult fileDel(String uuid) throws ServiceException {
    	OssFile ossFile = ossFileService.selectByPrimaryKey(uuid);
    	File file = new File(ossFile.getBucket()+ossFile.getDirPath());
		File[] files = file.listFiles();
		if(null != files && files.length>0) {
			for (File fileOne : files) {
				if(fileOne.getName().contains(uuid)) {
					fileOne.delete();
				}
			}
		}
    	ossFileService.deleteByPrimaryKey(uuid);
    	return AjaxResult.getSuccessrResult(true);
    }
}
